Package org.python.pydev.editorinput

Source Code of org.python.pydev.editorinput.PySourceLocatorBase

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.editorinput;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.part.FileEditorInput;
import org.python.pydev.core.IPyStackFrame;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.core.log.Log;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editor.codecompletion.revisited.PythonPathHelper;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.ui.filetypes.FileTypesPreferencesPage;

import com.aptana.shared_core.io.FileUtils;
import com.aptana.shared_core.structure.Tuple;

/**
* Refactored from the PydevPlugin: helpers to find some IFile / IEditorInput
* from a Path (or java.io.File)
*
* @author fabioz
*/
public class PySourceLocatorBase {

    /**
     * This method will try to find the most likely file that matches the given path,
     * considering:
     * - The workspace files
     * - The open editors
     *
     * and if all fails, it'll still ask the user which path should be used.
     *
     *
     * @param path
     * @return
     */
    public IEditorInput createEditorInput(IPath path) {
        return createEditorInput(path, true, null);
    }

    /**
     * @param file the file we want to get in the workspace
     * @return a workspace file that matches the given file.
     */
    public IFile getWorkspaceFile(File file) {
        IFile[] files = getWorkspaceFiles(file);
        return selectWorkspaceFile(files);
    }

    /**
     * @param file the file we want to get in the workspace
     * @return a workspace file that matches the given file.
     */
    public IFile[] getWorkspaceFiles(File file) {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IFile[] files = workspace.getRoot().findFilesForLocationURI(file.toURI());
        files = filterNonExistentFiles(files);
        if (files == null || files.length == 0) {
            return null;
        }

        return files;
    }

    public IContainer getWorkspaceContainer(File file) {
        IContainer[] containers = getWorkspaceContainers(file);
        if (containers == null || containers.length < 1) {
            return null;
        }
        return containers[0];
    }

    public IContainer[] getWorkspaceContainers(File file) {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IContainer[] containers = workspace.getRoot().findContainersForLocationURI(file.toURI());
        containers = filterNonExistentContainers(containers);
        if (containers == null || containers.length == 0) {
            return null;
        }

        return containers;
    }

    //---------------------------------- PRIVATE API BELOW --------------------------------------------

    /**
     * Creates the editor input from a given path.
     *
     * @param path the path for the editor input we're looking
     * @param askIfDoesNotExist if true, it'll try to ask the user/check existing editors and look
     * in the workspace for matches given the name
     *
     * @return the editor input found or none if None was available for the given path
     */
    public IEditorInput createEditorInput(IPath path, boolean askIfDoesNotExist, IPyStackFrame pyStackFrame) {
        int onSourceNotFound = PySourceLocatorPrefs.getOnSourceNotFound();
        IEditorInput edInput = null;

        String pathTranslation = PySourceLocatorPrefs.getPathTranslation(path);
        if (pathTranslation != null) {
            if (!pathTranslation.equals(PySourceLocatorPrefs.DONTASK)) {
                //change it for the registered translation
                path = Path.fromOSString(pathTranslation);
            } else {
                //DONTASK!!
                askIfDoesNotExist = false;
            }
        }

        IWorkspace w = ResourcesPlugin.getWorkspace();

        //let's start with the 'easy' way
        IFile fileForLocation = w.getRoot().getFileForLocation(path);
        if (fileForLocation != null && fileForLocation.exists()) {
            return new FileEditorInput(fileForLocation);
        }

        IFile files[] = w.getRoot().findFilesForLocation(path);
        if (files == null || files.length == 0 || !files[0].exists()) {
            //it is probably an external file
            File systemFile = path.toFile();
            if (systemFile.exists()) {
                edInput = createEditorInput(systemFile);
            }

            if (edInput == null) {
                //here we can do one more thing: if the file matches some opened editor, let's use it...
                //(this is done because when debugging, we don't want to be asked over and over
                //for the same file)
                IEditorInput input = getEditorInputFromExistingEditors(systemFile.getName());
                if (input != null) {
                    return input;
                }

                if (askIfDoesNotExist
                        && (onSourceNotFound == PySourceLocatorPrefs.ASK_FOR_FILE || onSourceNotFound == PySourceLocatorPrefs.ASK_FOR_FILE_GET_FROM_SERVER)) {

                    //this is the last resort... First we'll try to check for a 'good' match,
                    //and if there's more than one we'll ask it to the user
                    List<IFile> likelyFiles = getLikelyFiles(path, w);
                    IFile iFile = selectWorkspaceFile(likelyFiles.toArray(new IFile[0]));
                    if (iFile != null) {
                        PySourceLocatorPrefs.addPathTranslation(path, iFile.getLocation());
                        return new FileEditorInput(iFile);
                    }

                    //ok, ask the user for any file in the computer
                    IEditorInput pydevFileEditorInput = selectFilesystemFileForPath(path);
                    input = pydevFileEditorInput;
                    if (input != null) {
                        File file = PydevFileEditorInput.getFile(pydevFileEditorInput);
                        if (file != null) {
                            PySourceLocatorPrefs.addPathTranslation(path,
                                    Path.fromOSString(FileUtils.getFileAbsolutePath(file)));
                            return input;
                        }
                    }

                    PySourceLocatorPrefs.setIgnorePathTranslation(path);
                }
            }
        } else { //file exists
            IFile workspaceFile = selectWorkspaceFile(files);
            if (workspaceFile != null) {
                edInput = new FileEditorInput(workspaceFile);
            }
        }

        if (edInput == null
                && (onSourceNotFound == PySourceLocatorPrefs.ASK_FOR_FILE_GET_FROM_SERVER || onSourceNotFound == PySourceLocatorPrefs.GET_FROM_SERVER)) {
            if (pyStackFrame != null) {
                try {
                    String fileContents = pyStackFrame.getFileContents();
                    if (fileContents != null && fileContents.length() > 0) {
                        String lastSegment = path.lastSegment();
                        File workspaceMetadataFile = PydevPlugin.getWorkspaceMetadataFile("temporary_files");
                        if (!workspaceMetadataFile.exists()) {
                            workspaceMetadataFile.mkdirs();
                        }
                        File file = new File(workspaceMetadataFile, lastSegment);
                        try {
                            if (file.exists()) {
                                file.delete();
                            }
                        } catch (Exception e) {
                        }
                        FileUtils.writeStrToFile(fileContents, file);
                        try {
                            file.setReadOnly();
                        } catch (Exception e) {
                        }
                        edInput = PydevFileEditorInput.create(file, true);
                    }

                } catch (Exception e) {
                    Log.log(e);
                }

            }
        }
        return edInput;
    }

    /**
     * @param matchName the name to match in the editor
     * @return an editor input from an existing editor available
     */
    private IEditorInput getEditorInputFromExistingEditors(final String matchName) {
        final Tuple<IWorkbenchWindow, IEditorInput> workbenchAndReturn = new Tuple<IWorkbenchWindow, IEditorInput>(
                PlatformUI.getWorkbench().getActiveWorkbenchWindow(), null);

        Runnable r = new Runnable() {

            public void run() {
                IWorkbenchWindow workbenchWindow = workbenchAndReturn.o1;
                if (workbenchWindow == null) {
                    workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                }

                if (workbenchWindow == null) {
                    return;
                }

                IWorkbenchPage activePage = workbenchWindow.getActivePage();
                if (activePage == null) {
                    return;
                }

                IEditorReference[] editorReferences = activePage.getEditorReferences();
                for (IEditorReference editorReference : editorReferences) {
                    IEditorPart editor = editorReference.getEditor(false);
                    if (editor != null) {
                        if (editor instanceof PyEdit) {
                            PyEdit pyEdit = (PyEdit) editor;
                            IEditorInput editorInput = pyEdit.getEditorInput();
                            if (editorInput instanceof IPathEditorInput) {
                                IPathEditorInput pathEditorInput = (IPathEditorInput) editorInput;
                                IPath localPath = pathEditorInput.getPath();
                                if (localPath != null) {
                                    String considerName = localPath.segment(localPath.segmentCount() - 1);
                                    if (matchName.equals(considerName)) {
                                        workbenchAndReturn.o2 = editorInput;
                                        return;
                                    }
                                }
                            } else {
                                File editorFile = pyEdit.getEditorFile();
                                if (editorFile != null) {
                                    if (editorFile.getName().equals(matchName)) {
                                        workbenchAndReturn.o2 = editorInput;
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        };

        if (workbenchAndReturn.o1 == null) { //not ui-thread
            Display.getDefault().syncExec(r);
        } else {
            r.run();
        }

        return workbenchAndReturn.o2;
    }

    /**
     * This is the last resort... pointing to some filesystem file to get the editor for some path.
     */
    protected IEditorInput selectFilesystemFileForPath(final IPath path) {
        final List<String> l = new ArrayList<String>();
        Runnable r = new Runnable() {

            public void run() {
                Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                FileDialog dialog = new FileDialog(shell);
                dialog.setText(path + " - select correspondent filesystem file.");
                String[] wildcardValidSourceFiles = FileTypesPreferencesPage.getWildcardValidSourceFiles();
                wildcardValidSourceFiles = StringUtils.addString(wildcardValidSourceFiles, "*");
                dialog.setFilterExtensions(wildcardValidSourceFiles);
                String string = dialog.open();
                if (string != null) {
                    l.add(string);
                }
            }
        };
        if (Display.getCurrent() == null) { //not ui-thread
            Display.getDefault().syncExec(r);
        } else {
            r.run();
        }
        if (l.size() > 0) {
            String fileAbsolutePath = FileUtils.getFileAbsolutePath(l.get(0));
            return PydevFileEditorInput.create(new File(fileAbsolutePath), true);
        }
        return null;
    }

    /**
     * This method will pass all the files in the workspace and check if there's a file that might
     * be a match to some path (use only as an almost 'last-resort').
     */
    private List<IFile> getLikelyFiles(IPath path, IWorkspace w) {
        List<IFile> ret = new ArrayList<IFile>();
        try {
            IResource[] resources = w.getRoot().members();
            getLikelyFiles(path, ret, resources);
        } catch (CoreException e) {
            Log.log(e);
        }
        return ret;
    }

    /**
     * Used to recursively get the likely files given the first set of containers
     */
    private void getLikelyFiles(IPath path, List<IFile> ret, IResource[] resources) throws CoreException {
        String strPath = path.removeFileExtension().lastSegment().toLowerCase(); //this will return something as 'foo'

        for (IResource resource : resources) {
            if (resource instanceof IFile) {
                IFile f = (IFile) resource;

                if (PythonPathHelper.isValidSourceFile(f)) {
                    if (resource.getFullPath().removeFileExtension().lastSegment().toLowerCase().equals(strPath)) {
                        ret.add((IFile) resource);
                    }
                }
            } else if (resource instanceof IContainer) {
                getLikelyFiles(path, ret, ((IContainer) resource).members());
            }
        }
    }

    /**
     * Creates some editor input for the passed file
     * @param file the file for which an editor input should be created
     * @return the editor input that'll open the passed file.
     */
    private IEditorInput createEditorInput(File file) {
        IFile[] workspaceFile = getWorkspaceFiles(file);
        if (workspaceFile != null && workspaceFile.length > 0) {
            IFile file2 = selectWorkspaceFile(workspaceFile);
            if (file2 != null) {
                return new FileEditorInput(file2);
            } else {
                return new FileEditorInput(workspaceFile[0]);
            }
        }
        return PydevFileEditorInput.create(file, true);
    }

    /**
     * @param files the files that should be filtered
     * @return a new array of IFile with only the files that actually exist.
     */
    private IFile[] filterNonExistentFiles(IFile[] files) {
        if (files == null)
            return null;

        int length = files.length;
        ArrayList<IFile> existentFiles = new ArrayList<IFile>(length);
        for (int i = 0; i < length; i++) {
            if (files[i].exists())
                existentFiles.add(files[i]);
        }
        return (IFile[]) existentFiles.toArray(new IFile[existentFiles.size()]);
    }

    /**
     * @param containers the containers that should be filtered
     * @return a new array of IContainer with only the containers that actually exist.
     */
    public IContainer[] filterNonExistentContainers(IContainer[] containers) {
        if (containers == null)
            return null;

        int length = containers.length;
        ArrayList<IContainer> existentFiles = new ArrayList<IContainer>(length);
        for (int i = 0; i < length; i++) {
            if (containers[i].exists())
                existentFiles.add(containers[i]);
        }
        return (IContainer[]) existentFiles.toArray(new IContainer[existentFiles.size()]);
    }

    /**
     * Ask the user to select one file of the given list of files (if some is available)
     *
     * @param files the files available for selection.
     * @return the selected file (from the files passed) or null if there was no file available for
     * selection or if the user canceled it.
     */
    private IFile selectWorkspaceFile(final IFile[] files) {
        if (files == null || files.length == 0) {
            return null;
        }
        if (files.length == 1) {
            return files[0];
        }
        final List<IFile> selected = new ArrayList<IFile>();

        Runnable r = new Runnable() {
            public void run() {
                Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell, new PyFileLabelProvider());
                dialog.setElements(files);
                dialog.setTitle("Select Workspace File");
                dialog.setMessage("File may be matched to multiple files in the workspace.");
                if (dialog.open() == Window.OK) {
                    selected.add((IFile) dialog.getFirstResult());
                }
            }

        };
        if (Display.getCurrent() == null) { //not ui-thread
            Display.getDefault().syncExec(r);
        } else {
            r.run();
        }
        if (selected.size() > 0) {
            return selected.get(0);
        }
        return null;
    }
}
TOP

Related Classes of org.python.pydev.editorinput.PySourceLocatorBase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.